/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package services;

import dataModel.process.Activity;
import dataModel.process.Arc;
import dataModel.process.DataObject;
import dataModel.process.DataStore;
import dataModel.process.Element;
import dataModel.process.Event;
import dataModel.process.Gateway;
import dataModel.process.ProcessModel;
import de.hpi.bpt.graph.algo.rpst.RPST;
import de.hpi.bpt.graph.algo.rpst.RPSTNode;
import de.hpi.bpt.process.ControlFlow;
import de.hpi.bpt.process.Node;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.ArrayList;
import textPlanning.PlanningHelper;

/**
 *
 * @author Bruna
 */
public class IdentifyingHeuristics {
    
    public static void findWokflowHeuristic(RPSTNode<ControlFlow, Node> root, RPST<ControlFlow, Node> rpst, int level, ProcessModel model, List<ServiceInformation> servicesWorkflow){        
        // Order nodes of current level with respect to control flow
        ArrayList<RPSTNode<ControlFlow, Node>> orderedTopNodes = PlanningHelper.sortTreeLevel(root, root.getEntry(), rpst);
        // For each node of current level
        for (RPSTNode<ControlFlow, Node> node : orderedTopNodes) {

            int depth = PlanningHelper.getDepth(node, rpst);
            if (PlanningHelper.isBond(node)) {

                //**************************************  LOOP - SPLIT  **************************************
                ServiceInformation serviceLoop = hasLoop(node, rpst, model);
                if(serviceLoop != null){
                    servicesWorkflow.add(serviceLoop);
                }
                
                //**************************************  XOR - SPLIT  **************************************
                ServiceInformation serviceXOR = hasXOR(node, rpst, model);
                if(serviceXOR != null){
                    servicesWorkflow.add(serviceXOR);
                }

                //**************************************  OR - SPLIT  **************************************
                ServiceInformation serviceOR = hasOR(node, rpst, model);
                if(serviceOR != null){
                    servicesWorkflow.add(serviceOR);
                }
                
                //**************************************  AND - SPLIT  **************************************
                ServiceInformation serviceAND = hasAND(node, rpst, model);
                if(serviceAND != null){
                    servicesWorkflow.add(serviceAND);
                }

                // Convert to Text
                if (PlanningHelper.isLoop(node, rpst) || PlanningHelper.isSkip(node, rpst)) {
                    findWokflowHeuristic(node, rpst, level,model,servicesWorkflow);
                }
                if (PlanningHelper.isXORSplit(node, rpst) || PlanningHelper.isORSplit(node, rpst) || PlanningHelper.isEventSplit(node, rpst)) {
                    ArrayList<RPSTNode<ControlFlow, Node>> paths = PlanningHelper.sortTreeLevel(node, node.getEntry(), rpst);
                    for (RPSTNode<ControlFlow, Node> path : paths) {
                        findWokflowHeuristic(path, rpst, level + 1,model,servicesWorkflow);
                    }
                }
                if (PlanningHelper.isANDSplit(node, rpst)) {
                    // Determine path count
                    ArrayList<RPSTNode<ControlFlow, Node>> andNodes = PlanningHelper.sortTreeLevel(node, node.getEntry(), rpst);

                    if (andNodes.size() == 2) {
                        ArrayList<RPSTNode<ControlFlow, Node>> topNodes = PlanningHelper.sortTreeLevel(node, node.getEntry(), rpst);
                        RPSTNode<ControlFlow, Node> path1 = topNodes.get(0);
                        RPSTNode<ControlFlow, Node> path2 = topNodes.get(1);

                        // Convert both paths
                        findWokflowHeuristic(path1, rpst, level,model,servicesWorkflow);
                        findWokflowHeuristic(path2, rpst, level,model,servicesWorkflow);
                    } else {
                        ArrayList<RPSTNode<ControlFlow, Node>> paths = PlanningHelper.sortTreeLevel(node, node.getEntry(), rpst);
                        for (RPSTNode<ControlFlow, Node> path : paths) {
                            findWokflowHeuristic(path, rpst, level + 1,model,servicesWorkflow);
                        }
                    }
                }
            } else {
                if (depth > 0) {
                    findWokflowHeuristic(node, rpst, level,model,servicesWorkflow);
                }
            }
        }
    }
    
    private static ServiceInformation hasLoop(RPSTNode<ControlFlow, Node> node, RPST<ControlFlow, Node> rpst, ProcessModel model){
        
        ServiceInformation serv = null;
                
        if (PlanningHelper.isLoop(node, rpst)) {
                    
                    Collection<Node> vertices = node.getFragment().getConnectedVertices();
                    StringBuilder listActivitiesLoop = new StringBuilder();
                    List<String> allListActivitiesLoop = new LinkedList<String>();
                    
                    List<String> profile = new LinkedList<String>();
                    for (Node node1 : vertices) {
                        String nodeClass = node1.getClass().toString();
                        if(nodeClass.endsWith("Task")){
                            allListActivitiesLoop.add(node1.getName());
                            listActivitiesLoop.append(node1.getName());
                            listActivitiesLoop.append("_");
                            
                            int idActivity =  Integer.parseInt(node1.getId());
                            String prof = model.getActivity(idActivity).getLane().getName();
                            if(!profile.contains(prof)){
                                profile.add(prof);
                            }
                        }
                    }
                    int length = listActivitiesLoop.length();
                    listActivitiesLoop.deleteCharAt(length-1);
                    String lisActLoop = listActivitiesLoop.toString();
                    listActivitiesLoop.delete(31, length-1);                    
                    System.out.println("LOOP");
                    System.out.println("Nome: "+listActivitiesLoop);
                    serv = new ServiceInformation();
                    serv.setName(listActivitiesLoop.toString());
                    System.out.println("Tipo: ");
                    serv.setType(" ");
                                        
                    List<Activity> activities = new LinkedList<Activity>();
                    HashMap<Integer, Activity> allActs = model.getActivities();
                    for(int i=0;i<allListActivitiesLoop.size();i++){
                        for(int keyAct: allActs.keySet()){
                            if(allActs.get(keyAct).getLabel().equalsIgnoreCase(allListActivitiesLoop.get(i))){
                                activities.add(allActs.get(keyAct));
                            }
                        }                        
                    }
                    
                    List<String> dataObjectIsEntry = new LinkedList<String>();
                    List<String> dataObjectNotExit = new LinkedList<String>();
                    List<String> dataObjectIsExit = new LinkedList<String>();
                    HashMap<Integer, DataObject> allDatasObjs = model.getDataObjects();
                    HashMap<Integer, Arc> allArcs = model.getArcs();
                    //For each activity in the activiy list
                    for(int j=0; j<activities.size();j++){
                        
                        for(int keyArc: allArcs.keySet()){
                            //Verificando a saida                    
                            if(allArcs.get(keyArc).getSource().getId()==activities.get(j).getId()){
                                Element dataObjsExit = allArcs.get(keyArc).getTarget();
                                if(allDatasObjs.containsValue(dataObjsExit)){
                                    int count=0;
                                    for(int keyDataObj: allArcs.keySet()){
                                        //if( (  ( (allArcs.get(keyDataObj).getSource()==dataObjsExit) || (allArcs.get(keyDataObj).getTarget()==dataObjsExit)) && allArcs.get(keyDataObj).getType().equalsIgnoreCase("Association_Undirected") ) ){
                                        if( (allArcs.get(keyDataObj).getSource()==dataObjsExit) || (allArcs.get(keyDataObj).getTarget()==dataObjsExit)){
                                            if(allArcs.get(keyDataObj).getType().equalsIgnoreCase("Association_Undirected")){
                                                dataObjectNotExit.add(dataObjsExit.getLabel());
                                                count++;
                                            }
                                        }
                                    }
                                    if(count==0){
                                        dataObjectIsExit.add(dataObjsExit.getLabel());
                                    }
                                }
                            }
                        }
                    }
                    for(int j=0; j<activities.size();j++){
                        
                        for(int keyArc: allArcs.keySet()){
                            int count=0;
                            //verificando entrada
                            if(allArcs.get(keyArc).getTarget().getId()==activities.get(j).getId()){
                                Element dataObjsEntry = allArcs.get(keyArc).getSource();                        
                                if(allDatasObjs.containsValue(dataObjsEntry)){                            
                                    for(int keyDataObj: allArcs.keySet()){
                                        if( (  ( (allArcs.get(keyDataObj).getSource()==dataObjsEntry) || (allArcs.get(keyDataObj).getTarget()==dataObjsEntry)) && allArcs.get(keyDataObj).getType().equalsIgnoreCase("Association_Undirected") ) ){
                                            count++;
                                        }
                                    }                            
                                    if( (count==0) && (! (dataObjectNotExit.contains(dataObjsEntry.getLabel()))) ){
                                        if( !(dataObjectIsEntry.contains(dataObjsEntry.getLabel()) ) ){
                                            dataObjectIsEntry.add(dataObjsEntry.getLabel());
                                        }                                
                                    }                            
                                }
                            }
                        }
                       
                    }
                    
                    System.out.println("Entrada: "+dataObjectIsEntry);
                    //serv.setEntry(dataObjectIsEntry.toString());
                    serv.setEntry(dataObjectIsEntry);
                    System.out.println("Saida: "+dataObjectIsExit);
                    //serv.setExit(dataObjectIsExit.toString());
                    serv.setExit(dataObjectIsExit);
                    
                    System.out.println("Origem: Workflow Loop");
                    serv.setOrigin("Workflow Loop");
                    System.out.println("Atividades: "+allListActivitiesLoop);
                    serv.setActivities(allListActivitiesLoop);
                    System.out.println("Descricao: " + "A partir dos dados " + dataObjectIsEntry + "deve-se "+  listActivitiesLoop+".");
                    String descrip = "A partir dos dados " + dataObjectIsEntry.toString().toLowerCase() + "deve-se "+  listActivitiesLoop.toString().toLowerCase()+".";
                    
                    serv.setProfile(profile);
                    System.out.println("Perfil: " + serv.getProfile().toString());
                    
                    serv.setDescription(descrip);                    
                    
                    System.out.println("================");
                }
        return serv;        
    }
    
    private static ServiceInformation hasXOR(RPSTNode<ControlFlow, Node> node, RPST<ControlFlow, Node> rpst, ProcessModel model){
        ServiceInformation serv = null;
        
        if (PlanningHelper.isXORSplit(node, rpst)) {
                    Collection<Node> vertices = node.getFragment().getConnectedVertices();
                    StringBuilder listActivitiesXOR = new StringBuilder();
                    List<String> allListActivitiesXOR = new LinkedList();
                    List<String> profile = new LinkedList<String>();
                    for (Node node1 : vertices) {
                        String nodeClass = node1.getClass().toString();
                        if(nodeClass.endsWith("Task")){
                            allListActivitiesXOR.add(node1.getName());
                            listActivitiesXOR.append(node1.getName());
                            listActivitiesXOR.append("_");
                            
                            int idActivity =  Integer.parseInt(node1.getId());
                            String prof = model.getActivity(idActivity).getLane().getName();
                            if(!profile.contains(prof)){
                                profile.add(prof);
                            }
                            
                        }
                    }
                    int length = listActivitiesXOR.length();
                    listActivitiesXOR.deleteCharAt(length-1);
                    String listActXOR = listActivitiesXOR.toString();
                    //listActivitiesXOR.delete(31, length-1);
                    System.out.println("XOR");
                    System.out.println("Nome: "+listActivitiesXOR);
                    serv = new ServiceInformation();
                    serv.setName(listActivitiesXOR.toString());
                    System.out.println("Tipo: ");
                    serv.setType(" ");
                    
                    List<Activity> activities = new LinkedList<Activity>();
                    HashMap<Integer, Activity> allActs = model.getActivities();
                    for(int i=0;i< allListActivitiesXOR.size();i++){
                        for(int keyAct: allActs.keySet()){
                            if(allActs.get(keyAct).getLabel().equalsIgnoreCase(allListActivitiesXOR.get(i))){
                                activities.add(allActs.get(keyAct));
                            }
                        }                        
                    }
                    
                    List<String> dataObjectIsEntry = new LinkedList<String>();
                    List<String> dataObjectNotExit = new LinkedList<String>();
                    List<String> dataObjectIsExit = new LinkedList<String>();
                    HashMap<Integer, DataObject> allDatasObjs = model.getDataObjects();
                    HashMap<Integer, Arc> allArcs = model.getArcs();
                    //For each activity in the activiy list
                    for(int j=0; j<activities.size();j++){
                        
                        for(int keyArc: allArcs.keySet()){
                            //Verificando a saida                    
                            if(allArcs.get(keyArc).getSource().getId()==activities.get(j).getId()){
                                Element dataObjsExit = allArcs.get(keyArc).getTarget();
                                if(allDatasObjs.containsValue(dataObjsExit)){
                                    int count=0;
                                    for(int keyDataObj: allArcs.keySet()){
                                        //if( (  ( (allArcs.get(keyDataObj).getSource()==dataObjsExit) || (allArcs.get(keyDataObj).getTarget()==dataObjsExit)) && allArcs.get(keyDataObj).getType().equalsIgnoreCase("Association_Undirected") ) ){
                                        if( (allArcs.get(keyDataObj).getSource()==dataObjsExit) || (allArcs.get(keyDataObj).getTarget()==dataObjsExit)){
                                            if(allArcs.get(keyDataObj).getType().equalsIgnoreCase("Association_Undirected")){
                                                dataObjectNotExit.add(dataObjsExit.getLabel());
                                                count++;
                                            }
                                        }
                                    }
                                    if(count==0){
                                        dataObjectIsExit.add(dataObjsExit.getLabel());
                                    }
                                }
                            }
                        }
                    }
                    for(int j=0; j<activities.size();j++){
                        
                        for(int keyArc: allArcs.keySet()){
                            int count=0;
                            //verificando entrada
                            if(allArcs.get(keyArc).getTarget().getId()==activities.get(j).getId()){
                                Element dataObjsEntry = allArcs.get(keyArc).getSource();                        
                                if(allDatasObjs.containsValue(dataObjsEntry)){                            
                                    for(int keyDataObj: allArcs.keySet()){
                                        if( (  ( (allArcs.get(keyDataObj).getSource()==dataObjsEntry) || (allArcs.get(keyDataObj).getTarget()==dataObjsEntry)) && allArcs.get(keyDataObj).getType().equalsIgnoreCase("Association_Undirected") ) ){
                                            count++;
                                        }
                                    }                            
                                    if( (count==0) && (! (dataObjectNotExit.contains(dataObjsEntry.getLabel()))) ){
                                        if( !(dataObjectIsEntry.contains(dataObjsEntry.getLabel()) ) ){
                                            dataObjectIsEntry.add(dataObjsEntry.getLabel());
                                        }                                
                                    }                            
                                }
                            }
                        }
                       
                    }
                    
                    System.out.println("Entrada: "+dataObjectIsEntry);
                    //serv.setEntry(dataObjectIsEntry.toString());
                    serv.setEntry(dataObjectIsEntry);
                    System.out.println("Saida: "+dataObjectIsExit);
                    //serv.setExit(dataObjectIsExit.toString());
                    serv.setExit(dataObjectIsExit);
                    System.out.println("Origem: Workflow XOR");
                    serv.setOrigin("Workflow XOR");
                    System.out.println("Atividades: "+allListActivitiesXOR);
                    serv.setActivities(allListActivitiesXOR);
                    System.out.println("Descricao: " + "A partir dos dados " + dataObjectIsEntry + "deve-se "+  listActivitiesXOR+".");
                    String descrip = "A partir dos dados " + dataObjectIsEntry.toString().toLowerCase() + "deve-se "+  listActivitiesXOR.toString().toLowerCase()+".";
                    serv.setDescription(descrip);
                    
                    serv.setProfile(profile);
                    System.out.println("Perfil: " + serv.getProfile().toString());
                    
                    System.out.println("================");
                }
        return serv;
        
    }
    
    private static ServiceInformation hasOR(RPSTNode<ControlFlow, Node> node, RPST<ControlFlow, Node> rpst, ProcessModel model){
        
        ServiceInformation serv = null;
        
        if (PlanningHelper.isORSplit(node, rpst)) {
                    Collection<Node> vertices = node.getFragment().getConnectedVertices();
                    StringBuilder listActivitiesOR = new StringBuilder();
                    List<String> allListActivitiesOR = new LinkedList<String>();
                    List<String> profile = new LinkedList<String>();
                    for (Node node1 : vertices) {
                        String nodeClass = node1.getClass().toString();
                        if(nodeClass.endsWith("Task")){
                            allListActivitiesOR.add(node1.getName());
                            listActivitiesOR.append(node1.getName());
                            listActivitiesOR.append("_");
                            
                            int idActivity =  Integer.parseInt(node1.getId());
                            String prof = model.getActivity(idActivity).getLane().getName();
                            if(!profile.contains(prof)){
                                profile.add(prof);
                            }
                        }
                    }
                    int length = listActivitiesOR.length();
                    listActivitiesOR.deleteCharAt(length-1);
                    String listActOR = listActivitiesOR.toString();
                    listActivitiesOR.delete(31, length-1);
                    System.out.println("OR");
                    System.out.println();
                    System.out.println("Nome: "+listActivitiesOR);
                    serv = new ServiceInformation();
                    serv.setName(listActivitiesOR.toString());
                    System.out.println("Tipo: ");
                    serv.setType(" ");
                    
                    List<Activity> activities = new LinkedList<Activity>();
                    HashMap<Integer, Activity> allActs = model.getActivities();
                    for(int i=0;i<allListActivitiesOR.size();i++){
                        for(int keyAct: allActs.keySet()){
                            if(allActs.get(keyAct).getLabel().equalsIgnoreCase(allListActivitiesOR.get(i))){
                                activities.add(allActs.get(keyAct));
                            }
                        }                        
                    }
                    
                    List<String> dataObjectIsEntry = new LinkedList<String>();
                    List<String> dataObjectNotExit = new LinkedList<String>();
                    List<String> dataObjectIsExit = new LinkedList<String>();
                    HashMap<Integer, DataObject> allDatasObjs = model.getDataObjects();
                    HashMap<Integer, Arc> allArcs = model.getArcs();
                    //For each activity in the activiy list
                    for(int j=0; j<activities.size();j++){
                        
                        for(int keyArc: allArcs.keySet()){
                            //Verificando a saida                    
                            if(allArcs.get(keyArc).getSource().getId()==activities.get(j).getId()){
                                Element dataObjsExit = allArcs.get(keyArc).getTarget();
                                if(allDatasObjs.containsValue(dataObjsExit)){
                                    int count=0;
                                    for(int keyDataObj: allArcs.keySet()){
                                        //if( (  ( (allArcs.get(keyDataObj).getSource()==dataObjsExit) || (allArcs.get(keyDataObj).getTarget()==dataObjsExit)) && allArcs.get(keyDataObj).getType().equalsIgnoreCase("Association_Undirected") ) ){
                                        if( (allArcs.get(keyDataObj).getSource()==dataObjsExit) || (allArcs.get(keyDataObj).getTarget()==dataObjsExit)){
                                            if(allArcs.get(keyDataObj).getType().equalsIgnoreCase("Association_Undirected")){
                                                dataObjectNotExit.add(dataObjsExit.getLabel());
                                                count++;
                                            }
                                        }
                                    }
                                    if(count==0){
                                        dataObjectIsExit.add(dataObjsExit.getLabel());
                                    }
                                }
                            }
                        }
                    }
                    for(int j=0; j<activities.size();j++){
                        
                        for(int keyArc: allArcs.keySet()){
                            int count=0;
                            //verificando entrada
                            if(allArcs.get(keyArc).getTarget().getId()==activities.get(j).getId()){
                                Element dataObjsEntry = allArcs.get(keyArc).getSource();                        
                                if(allDatasObjs.containsValue(dataObjsEntry)){                            
                                    for(int keyDataObj: allArcs.keySet()){
                                        if( (  ( (allArcs.get(keyDataObj).getSource()==dataObjsEntry) || (allArcs.get(keyDataObj).getTarget()==dataObjsEntry)) && allArcs.get(keyDataObj).getType().equalsIgnoreCase("Association_Undirected") ) ){
                                            count++;
                                        }
                                    }                            
                                    if( (count==0) && (! (dataObjectNotExit.contains(dataObjsEntry.getLabel()))) ){
                                        if( !(dataObjectIsEntry.contains(dataObjsEntry.getLabel()) ) ){
                                            dataObjectIsEntry.add(dataObjsEntry.getLabel());
                                        }                                
                                    }                            
                                }
                            }
                        }
                       
                    }
                    
                    System.out.println("Entrada: "+dataObjectIsEntry);
                    //serv.setEntry(dataObjectIsEntry.toString());
                    serv.setEntry(dataObjectIsEntry);
                    System.out.println("Saida: "+dataObjectIsExit);
                    //serv.setExit(dataObjectIsExit.toString());
                    serv.setExit(dataObjectIsExit);
                    System.out.println("Origem: Workflow OR");
                    serv.setOrigin("Workflow OR");
                    System.out.println("Atividades: "+allListActivitiesOR);
                    serv.setActivities(allListActivitiesOR);
                    System.out.println("Descricao: " + "A partir dos dados " + dataObjectIsEntry + "deve-se "+  listActivitiesOR+".");
                    String descrip = "A partir dos dados " + dataObjectIsEntry.toString().toLowerCase() + "deve-se "+  listActivitiesOR.toString().toLowerCase()+".";
                    serv.setDescription(descrip);

                    serv.setProfile(profile);
                    System.out.println("Perfil: " + serv.getProfile().toString());
                
                    System.out.println("================");
                }
        return serv;
    }
    
    private static ServiceInformation hasAND(RPSTNode<ControlFlow, Node> node, RPST<ControlFlow, Node> rpst, ProcessModel model){
        
        ServiceInformation serv = null;
        
        if (PlanningHelper.isANDSplit(node, rpst)) {
                    Collection<Node> vertices = node.getFragment().getConnectedVertices();
                    StringBuilder listActivitiesAND = new StringBuilder();
                    List<String> allListActivitiesAND = new LinkedList<String>();
                    List<String> profile = new LinkedList<String>();
                    for (Node node1 : vertices) {
                        String nodeClass = node1.getClass().toString();
                        if(nodeClass.endsWith("Task")){
                            allListActivitiesAND.add(node1.getName());
                            listActivitiesAND.append(node1.getName());
                            listActivitiesAND.append("_");
                            
                            int idActivity =  Integer.parseInt(node1.getId());
                            String prof = model.getActivity(idActivity).getLane().getName();
                            if(!profile.contains(prof)){
                                profile.add(prof);
                            }
                            
                        }
                    }
                    int length = listActivitiesAND.length();
                    listActivitiesAND.deleteCharAt(length-1);
                    String listActsAND = listActivitiesAND.toString();
                    listActivitiesAND.delete(31, length-1);
                    System.out.println("AND");
                    System.out.println("Nome: "+ listActivitiesAND);
                    serv = new ServiceInformation();
                    serv.setName(listActivitiesAND.toString());
                    System.out.println("Tipo: ");
                    serv.setType(" ");
                    
                    List<Activity> activities = new LinkedList<Activity>();
                    HashMap<Integer, Activity> allActs = model.getActivities();
                    for(int i=0;i<allListActivitiesAND.size();i++){
                        for(int keyAct: allActs.keySet()){
                            if(allActs.get(keyAct).getLabel().equalsIgnoreCase(allListActivitiesAND.get(i))){
                                activities.add(allActs.get(keyAct));
                            }
                        }                        
                    }
                    
                    List<String> dataObjectIsEntry = new LinkedList<String>();
                    List<String> dataObjectNotExit = new LinkedList<String>();
                    List<String> dataObjectIsExit = new LinkedList<String>();
                    HashMap<Integer, DataObject> allDatasObjs = model.getDataObjects();
                    HashMap<Integer, Arc> allArcs = model.getArcs();
                    //For each activity in the activiy list
                    for(int j=0; j<activities.size();j++){
                        
                        for(int keyArc: allArcs.keySet()){
                            //Verificando a saida                    
                            if(allArcs.get(keyArc).getSource().getId()==activities.get(j).getId()){
                                Element dataObjsExit = allArcs.get(keyArc).getTarget();
                                if(allDatasObjs.containsValue(dataObjsExit)){
                                    int count=0;
                                    for(int keyDataObj: allArcs.keySet()){
                                        //if( (  ( (allArcs.get(keyDataObj).getSource()==dataObjsExit) || (allArcs.get(keyDataObj).getTarget()==dataObjsExit)) && allArcs.get(keyDataObj).getType().equalsIgnoreCase("Association_Undirected") ) ){
                                        if( (allArcs.get(keyDataObj).getSource()==dataObjsExit) || (allArcs.get(keyDataObj).getTarget()==dataObjsExit)){
                                            if(allArcs.get(keyDataObj).getType().equalsIgnoreCase("Association_Undirected")){
                                                dataObjectNotExit.add(dataObjsExit.getLabel());
                                                count++;
                                            }
                                        }
                                    }
                                    if(count==0){
                                        dataObjectIsExit.add(dataObjsExit.getLabel());
                                    }
                                }
                            }
                        }
                    }
                    for(int j=0; j<activities.size();j++){
                        
                        for(int keyArc: allArcs.keySet()){
                            int count=0;
                            //verificando entrada
                            if(allArcs.get(keyArc).getTarget().getId()==activities.get(j).getId()){
                                Element dataObjsEntry = allArcs.get(keyArc).getSource();                        
                                if(allDatasObjs.containsValue(dataObjsEntry)){                            
                                    for(int keyDataObj: allArcs.keySet()){
                                        if( (  ( (allArcs.get(keyDataObj).getSource()==dataObjsEntry) || (allArcs.get(keyDataObj).getTarget()==dataObjsEntry)) && allArcs.get(keyDataObj).getType().equalsIgnoreCase("Association_Undirected") ) ){
                                            count++;
                                        }
                                    }                            
                                    if( (count==0) && (! (dataObjectNotExit.contains(dataObjsEntry.getLabel()))) ){
                                        if( !(dataObjectIsEntry.contains(dataObjsEntry.getLabel()) ) ){
                                            dataObjectIsEntry.add(dataObjsEntry.getLabel());
                                        }                                
                                    }                            
                                }
                            }
                        }
                       
                    }
                    
                    System.out.println("Entrada: "+dataObjectIsEntry);
                    //serv.setEntry(dataObjectIsEntry.toString());
                    serv.setEntry(dataObjectIsEntry);
                    System.out.println("Saida: "+dataObjectIsExit);
                    //serv.setExit(dataObjectIsExit.toString());
                    serv.setExit(dataObjectIsExit);
                    
                    System.out.println("Origem: Workflow AND");
                    serv.setOrigin("Workflow AND");
                    System.out.println("Atividades: "+ allListActivitiesAND);
                    serv.setActivities(allListActivitiesAND);
                    System.out.println("Descricao: " + "A partir dos dados " + dataObjectIsEntry + "deve-se "+  listActivitiesAND+".");
                    String descrip = "A partir dos dados " + dataObjectIsEntry.toString().toLowerCase() + "deve-se "+  listActivitiesAND.toString().toLowerCase()+".";
                    serv.setDescription(descrip);

                    serv.setProfile(profile);
                    System.out.println("Perfil: " + serv.getProfile().toString());
                    
                    System.out.println("================");
                }
        return serv;
    }
    
    public static List<ServiceInformation> findBusinessRules(ProcessModel model) {
        List<ServiceInformation> services = new LinkedList<ServiceInformation>();
        
        HashMap<Integer,Activity> atividades = model.getActivities();
        HashMap<Integer, Arc> arcos = model.getArcs();
        for(int key: atividades.keySet() ){
            if(atividades.get(key).getType() == 3){
                
                ServiceInformation serv = new ServiceInformation();
                System.out.println("Nome: " + atividades.get(key).getLabel());
                serv.setName(atividades.get(key).getLabel());
                System.out.println("Tipo: "); 
                serv.setType(" ");                
                StringBuilder entrada = new StringBuilder();
                List<String> entryAssociated = new LinkedList<String>();
                for(int keyArc: arcos.keySet()){                
                    if(arcos.get(keyArc).getTarget().getId()== atividades.get(key).getId()){
                        int idSource = arcos.get(keyArc).getSource().getId();
                        HashMap<Integer,DataObject> dataObjs = model.getDataObjects();
                        if(dataObjs.containsKey(idSource)){
                            DataObject data = dataObjs.get(idSource);
                            int i =0;
                            for(int keyArcDataobj: arcos.keySet()){
                                if (arcos.get(keyArcDataobj).getSource().getId() == dataObjs.get(idSource).getId()) {
                                    i++;                                   
                                }
                                if (arcos.get(keyArcDataobj).getTarget().getId() == dataObjs.get(idSource).getId()) {
                                    i++;
                                }
                            }
                            if(i==1){
                                entrada.append(dataObjs.get(idSource).getLabel());
                                entrada.append(", ");
                                entryAssociated.add(dataObjs.get(idSource).getLabel());
                            }
                        }
                    }
                }
                if(!(entrada.toString().isEmpty())){
                    int lenght = entrada.length();
                    entrada.delete(lenght-2, lenght-1);
                }
                System.out.println("Entrada: " + entrada);
                //serv.setEntry(entrada.toString());
                serv.setEntry(entryAssociated);
                
                StringBuilder saida = new StringBuilder();
                List<String> exitAssociated = new LinkedList<String>();
                for(int keyArc: arcos.keySet()){                
                    if(arcos.get(keyArc).getSource().getId()== atividades.get(key).getId()){
                        int idTarget = arcos.get(keyArc).getTarget().getId();
                        HashMap<Integer,DataObject> dataObjs = model.getDataObjects();
                        if(dataObjs.containsKey(idTarget)){
                            DataObject data = dataObjs.get(idTarget);
                            int i =0;
                            for(int keyArcDataobj: arcos.keySet()){
                                if (arcos.get(keyArcDataobj).getSource().getId() == dataObjs.get(idTarget).getId()) {
                                    i++;                                   
                                }
                                if (arcos.get(keyArcDataobj).getTarget().getId() == dataObjs.get(idTarget).getId()) {
                                    i++;
                                }
                            }
                            if(i==1){
                                saida.append(dataObjs.get(idTarget).getLabel());
                                saida.append(", ");
                                exitAssociated.add(dataObjs.get(idTarget).getLabel());
                            }
                        }
                    }
                }
                if(!(saida.toString().isEmpty())){
                    int lenghtSaida = saida.length();
                    saida.delete(lenghtSaida-2, lenghtSaida-1);
                }               
                
                System.out.println("Saida: "+ saida.toString());
                //serv.setExit(saida.toString());
                serv.setExit(exitAssociated);
                System.out.println("Origem: " + "Regras de Negocio");
                serv.setOrigin("Regras de Negocio");
                List<String> allActivities = new LinkedList<String>();
                allActivities.add(atividades.get(key).getLabel());
                System.out.println("Atividades: " + allActivities);
                serv.setActivities(allActivities);
                System.out.println("Descricao: " + "A partir dos dados " + entrada + "deve-se "+  atividades.get(key).getLabel()+".");
                String descrip = "A partir dos dados " + entrada.toString().toLowerCase() + "deve-se "+  atividades.get(key).getLabel().toLowerCase()+".";
                serv.setDescription(descrip);
                
                String prof = atividades.get(key).getLane().getName();
                List<String> profile = new LinkedList<String>();
                profile.add(prof);
                serv.setProfile(profile);
                System.out.println("Perfil: " + serv.getProfile().toString());
                
                services.add(serv);
            }
            
        }
        List<ServiceInformation> listServices = deleteSameServices(services);
        return listServices;
    }
    
    public static List<ServiceInformation> findMultipleInstance(ProcessModel model) {
        List<ServiceInformation> services = new LinkedList<ServiceInformation>();
        
        HashMap<Integer,Activity> atividades = model.getActivities();
        for(int key: atividades.keySet() ){
            if(!atividades.get(key).getLooptype().toLowerCase().equals("none")){                
                ServiceInformation serv = new ServiceInformation();
                
                System.out.println("Nome: " + atividades.get(key).getLabel());
                serv.setName(atividades.get(key).getLabel());
                System.out.println("Tipo: ");
                serv.setType(" ");
                StringBuilder entrada = new StringBuilder();
                List<String> entryAssociated = new LinkedList<String>();
                HashMap<Integer, Arc> arcos = model.getArcs();
                for(int keyArc: arcos.keySet()){                
                    if(arcos.get(keyArc).getTarget().getId()== atividades.get(key).getId()){
                        int idSource = arcos.get(keyArc).getSource().getId();
                        HashMap<Integer,DataObject> dataObjs = model.getDataObjects();
                        if(dataObjs.containsKey(idSource)){
                            DataObject data = dataObjs.get(idSource);
                            int i =0;
                            for(int keyArcDataobj: arcos.keySet()){
                                if (arcos.get(keyArcDataobj).getSource().getId() == dataObjs.get(idSource).getId()) {
                                    i++;                                   
                                }
                                if (arcos.get(keyArcDataobj).getTarget().getId() == dataObjs.get(idSource).getId()) {
                                    i++;
                                }
                            }
                            if(i==1){
                                entrada.append(dataObjs.get(idSource).getLabel());
                                entrada.append(", ");
                                entryAssociated.add(dataObjs.get(idSource).getLabel());
                            }
                        }
                    }
                }
                if(!(entrada.toString().isEmpty())){
                    int lenght = entrada.length();
                    entrada.delete(lenght-2, lenght-1);
                }
                System.out.println("Entrada: " + entrada);
                //serv.setEntry(entrada.toString());
                serv.setEntry(entryAssociated);
                
                StringBuilder saida = new StringBuilder();
                List<String> exitAssociated = new LinkedList();
                //HashMap<Integer, Arc> arcos = model.getArcs();
                for(int keyArc: arcos.keySet()){                
                    if(arcos.get(keyArc).getSource().getId()== atividades.get(key).getId()){
                        int idTarget = arcos.get(keyArc).getTarget().getId();
                        HashMap<Integer,DataObject> dataObjs = model.getDataObjects();
                        if(dataObjs.containsKey(idTarget)){
                            DataObject data = dataObjs.get(idTarget);
                            int i =0;
                            for(int keyArcDataobj: arcos.keySet()){
                                if (arcos.get(keyArcDataobj).getSource().getId() == dataObjs.get(idTarget).getId()) {
                                    i++;                                   
                                }
                                if (arcos.get(keyArcDataobj).getTarget().getId() == dataObjs.get(idTarget).getId()) {
                                    i++;
                                }
                            }
                            if(i==1){
                                saida.append(dataObjs.get(idTarget).getLabel());
                                saida.append(", ");
                                exitAssociated.add(dataObjs.get(idTarget).getLabel());
                            }
                        }
                    }
                }
                if(!(saida.toString().isEmpty())){
                    int lenghtSaida = saida.length();
                    saida.delete(lenghtSaida-2, lenghtSaida-1);
                }               
                
                System.out.println("Saida: "+ saida.toString());
                //serv.setExit(saida.toString());
                serv.setExit(exitAssociated);
                System.out.println("Origem: " + "Multipla Instancia");
                serv.setOrigin("Multipla Instancia");
                List<String> allActivities = new LinkedList<String>();
                allActivities.add(atividades.get(key).getLabel());
                System.out.println("Atividades: " + allActivities);
                serv.setActivities(allActivities);
                System.out.println("Descricao: " + "A partir dos dados " + entrada + "deve-se "+  atividades.get(key).getLabel()+".");
                String descrip = "A partir dos dados " + entrada.toString().toLowerCase() + "deve-se "+  atividades.get(key).getLabel().toLowerCase()+".";
                serv.setDescription(descrip);
                
                String prof = atividades.get(key).getLane().getName();
                List<String> profile = new LinkedList<String>();
                profile.add(prof);
                serv.setProfile(profile);
                System.out.println("Perfil: " + serv.getProfile().toString());
                
                services.add(serv);
            }
            
        }
        List<ServiceInformation> listServices = deleteSameServices(services);
        return listServices;
    }
    
    public static List<ServiceInformation> findDataStore(ProcessModel model) {
        List<ServiceInformation> serv = new LinkedList<ServiceInformation>();
        
        HashMap<Integer,DataObject> dataObjects = model.getDataObjects();
        HashMap<Integer,DataStore> dataStores = model.getDataStores();
        HashMap<Integer, Activity> activities = model.getActivities();
        
        HashMap<Integer,Arc> arcos = model.getArcs();
        
        for(int keyDataStor: dataStores.keySet()){
            for(int keyArc: arcos.keySet()){
                
                if( (arcos.get(keyArc).getSource().getId()== dataStores.get(keyDataStor).getId()) ||
                        (arcos.get(keyArc).getTarget().getId()== dataStores.get(keyDataStor).getId()) ){
                    for(int keyDataObj: dataObjects.keySet()){
                        if( (arcos.get(keyArc).getTarget().getId() == dataObjects.get(keyDataObj).getId()) ||
                                (arcos.get(keyArc).getSource().getId() == dataObjects.get(keyDataObj).getId()) ){
                            
                            ServiceInformation service = new ServiceInformation();
                            List<String> allActivites = new LinkedList<String>();
                            for(int keyArcUnidire: arcos.keySet()){
                                if(dataObjects.get(keyDataObj).getId() == arcos.get(keyArcUnidire).getSource().getId()){
                                    Element target = arcos.get(keyArcUnidire).getTarget();
                                    if(activities.containsValue(target)){
                                        allActivites.add(target.getLabel());
                                        
                                        System.out.println("Nome: Armazenar "+dataObjects.get(keyDataObj).getLabel());
                                        service.setName("Armazenar "+dataObjects.get(keyDataObj).getLabel());
                                        service.setOriginalName(dataObjects.get(keyDataObj).getLabel());
                                        String type = "Dados (escrita)";
                                        System.out.println("Tipo: "+type);
                                        service.setType(type);
                                        System.out.println("Entrada: ");
                                        //service.setEntry("");
                                        service.setEntry(new LinkedList<String>());
                                        System.out.println("Saida: "+dataObjects.get(keyDataObj).getLabel());
                                        //service.setExit(dataObjects.get(keyDataObj).getLabel());
                                        List<String> saidasAssociados = new LinkedList<String>();
                                        saidasAssociados.add(dataObjects.get(keyDataObj).getLabel());
                                        //service.setExit(dataObjects.get(keyDataObj).getLabel());
                                        service.setExit(saidasAssociados);
                                        System.out.println("Descricao: " + "A partir dos dados deve-se armazenar "+  dataObjects.get(keyDataObj).getLabel()+".");
                                        String descrip = "A partir dos dados deve-se armazenar "+  dataObjects.get(keyDataObj).getLabel().toLowerCase()+".";
                                        service.setDescription(descrip);
                                    }
                                }
                                if(dataObjects.get(keyDataObj).getId() == arcos.get(keyArcUnidire).getTarget().getId()){
                                    Element source = arcos.get(keyArcUnidire).getSource();
                                    if(activities.containsValue(source)){
                                        allActivites.add(source.getLabel());
                                        
                                        System.out.println("Nome: Obter "+dataObjects.get(keyDataObj).getLabel());
                                        service.setName("Obter "+dataObjects.get(keyDataObj).getLabel());
                                        service.setOriginalName(dataObjects.get(keyDataObj).getLabel());
                                        String type = "Dados (leitura)";
                                        System.out.println("Tipo: "+type);
                                        service.setType(type);
                                        System.out.println("Entrada: "+dataObjects.get(keyDataObj).getLabel());
                                        List<String> entradaAssociados = new LinkedList<String>();
                                        entradaAssociados.add(dataObjects.get(keyDataObj).getLabel());
                                        //service.setEntry(dataObjects.get(keyDataObj).getLabel());
                                        service.setEntry(entradaAssociados);
                                        String entrada = dataObjects.get(keyDataObj).getLabel();
                                        System.out.println("Saida: ");
                                        //service.setExit("");
                                        service.setExit(new LinkedList<String>());
                                        System.out.println("Descricao: " + "A partir dos dados " + /*entrada +*/ "deve-se obter "+  dataObjects.get(keyDataObj).getLabel()+".");
                                        String descrip = "A partir dos dados " + entrada.toLowerCase() + "deve-se obter "+  dataObjects.get(keyDataObj).getLabel().toLowerCase()+".";
                                        service.setDescription(descrip);
                                    }
                                }                                  
                            }                           
                            System.out.println("Atividades: "+allActivites);
                            service.setActivities(allActivites);
                            
                            System.out.println("Origem: Cluster");
                            service.setOrigin("Cluster");
                                                      
                            
                            String prof = dataObjects.get(keyDataObj).getLane().getName();
                            List<String> profile = new LinkedList<String>();
                            profile.add(prof);
                            service.setProfile(profile);
                            System.out.println("Perfil: " + service.getProfile().toString());
                            
                            System.out.println("---------------");
                            
                            serv.add(service);
                        }
                    }
                }                
            }
        }
        List<ServiceInformation> listServices = deleteSameServices(serv);
        return listServices;
    }
    
    public static List<List> printAndSetSequentialActivities(List<List> ativSeqs, ProcessModel model){
        int i =1;
        List<List> allservices = new LinkedList<List>();
        for (List list : ativSeqs) {
            System.out.println("-----Atividades Sequencias "+i+" ------");
            List<Activity> a = list;
            StringBuilder nomesAtivs = new StringBuilder();
            List<String> allActivities = new LinkedList<String>();
            
            List<String> profile = new LinkedList<String>();            
            for (Activity ativi : a) {
                allActivities.add(ativi.getLabel());
                nomesAtivs.append(ativi.getLabel());
                nomesAtivs.append("_");
                String prof = ativi.getLane().getName();
                if(!profile.contains(prof)){
                    profile.add(prof);
                }
            }
            i++;
            int lenght = nomesAtivs.length();
            nomesAtivs.deleteCharAt(lenght-1);
            String listActs = nomesAtivs.toString();
            nomesAtivs.delete(31, lenght);
            
            List<ServiceInformation> servicesActivities = new LinkedList<ServiceInformation>();
            ServiceInformation ser = new ServiceInformation();
            System.out.println("Nome: "+nomesAtivs);
            ser.setName(nomesAtivs.toString());
            System.out.println("Tipo: ");
            ser.setType(" ");
            
            List<String> dataObjectIsEntry = new LinkedList<String>();
            List<String> dataObjectNotExit = new LinkedList<String>();
            List<String> dataObjectIsExit = new LinkedList<String>();
            HashMap<Integer, DataObject> allDatasObjs = model.getDataObjects();
            HashMap<Integer,DataStore> allDataStores = model.getDataStores();
            HashMap<Integer, Arc> allArcs = model.getArcs();
            //For each activity in the activiy list
            for(int j=0; j<a.size();j++){                
                for(int keyArc: allArcs.keySet()){
                    //Verificando a saida                    
                    if(allArcs.get(keyArc).getSource().getId()==a.get(j).getId()){
                        Element dataObjsExit = allArcs.get(keyArc).getTarget();
                        if(allDatasObjs.containsValue(dataObjsExit)){
                            int count=0;
                            for(int keyDataObj: allArcs.keySet()){
                                //if( (  ( (allArcs.get(keyDataObj).getSource()==dataObjsExit) || (allArcs.get(keyDataObj).getTarget()==dataObjsExit)) && allArcs.get(keyDataObj).getType().equalsIgnoreCase("Association_Undirected") ) ){
                                if( (allArcs.get(keyDataObj).getSource()==dataObjsExit) || (allArcs.get(keyDataObj).getTarget()==dataObjsExit)){
                                    if(allArcs.get(keyDataObj).getType().equalsIgnoreCase("Association_Undirected")){
                                        dataObjectNotExit.add(dataObjsExit.getLabel());
                                        count++;
                                    }
                                }
                            }
                            if(count==0){
                                dataObjectIsExit.add(dataObjsExit.getLabel());
                            }
                        }
                    }
                    
                    int count=0;
                    //verificando entrada
                    if(allArcs.get(keyArc).getTarget().getId()==a.get(j).getId()){
                        Element dataObjsEntry = allArcs.get(keyArc).getSource();                        
                        if(allDatasObjs.containsValue(dataObjsEntry)){                            
                            for(int keyDataObj: allArcs.keySet()){
                                if( (  ( (allArcs.get(keyDataObj).getSource()==dataObjsEntry) || (allArcs.get(keyDataObj).getTarget()==dataObjsEntry)) && allArcs.get(keyDataObj).getType().equalsIgnoreCase("Association_Undirected") ) ){
                                    count++;
                                }
                            }                            
                            if( (count==0) && (! (dataObjectNotExit.contains(dataObjsEntry.getLabel()))) ){
                                if( !(dataObjectIsEntry.contains(dataObjsEntry.getLabel()) ) ){
                                    dataObjectIsEntry.add(dataObjsEntry.getLabel());
                                }                                
                            }                            
                        }
                    }                    
               }
                
            }           
            
            System.out.println("Entrada: "+dataObjectIsEntry);
            //ser.setEntry(dataObjectIsEntry.toString());
            ser.setEntry(dataObjectIsEntry);
            System.out.println("Saida: "+dataObjectIsExit);
            //ser.setExit(dataObjectIsExit.toString());
            ser.setExit(dataObjectIsExit);
            System.out.println("Origem: Atividades Sequenciais");
            ser.setOrigin("Atividades Sequenciais");
            System.out.println("Atividades: "+allActivities);
            ser.setActivities(allActivities);
            System.out.println("Descricao: " + "A partir dos dados " + dataObjectIsEntry + "deve-se obter "+ nomesAtivs + ".");
            String descrip = "A partir dos dados " + dataObjectIsEntry.toString().toLowerCase() + "deve-se obter "+ nomesAtivs.toString().toLowerCase() + ".";
            ser.setDescription(descrip);
            
            ser.setProfile(profile);
            System.out.println("Perfil: " + ser.getProfile().toString());
            
            System.out.println("---------------");         
            servicesActivities.add(ser);
            allservices.add(servicesActivities);
        }
        List<List> allActsServices = new LinkedList<List>();
        for (List list : allservices) {
            List<ServiceInformation> activitiesList = list;
            List<ServiceInformation> listSequenceActivities = deleteSameServices(activitiesList);            
            allActsServices.add(listSequenceActivities);
        }
        
        return allActsServices;
    }
    
    public static void transformToAdjancencyList(ProcessModel model){
        HashMap<Integer, Activity> atividades = model.getActivities();
        HashMap<Integer, Gateway> gateways = model.getGateways();
        HashMap<Integer, Event> eventos = model.getEvents();
        HashMap<Integer, DataObject> dataObjects = model.getDataObjects();
        HashMap<Integer, DataStore> dataStores = model.getDataStores();
        HashMap<Integer, Arc> arcos = model.getArcs();
        
        HashMap<Element, List<Element>> todosOsElementos = new HashMap<Element, List<Element>>();
        
        //Para todas as atividades
        for (Activity ativ : atividades.values()) {
            List<Element> ligados = new LinkedList<Element>();
            for(Arc arco: arcos.values() ){
                if(arco.getSource() == ativ){
                    ligados.add(arco.getTarget());
                }
            }
            ativ.setTipo("Atividade");
            todosOsElementos.put(ativ, ligados);
            
        }
        //Para Todos os Eventos
        for (Event event : eventos.values()) {
            List<Element> ligados = new LinkedList<Element>();
            for(Arc arco: arcos.values() ){
                if(arco.getSource() == event){
                    ligados.add(arco.getTarget());
                }
            }
            event.setTipo("Evento");
            todosOsElementos.put(event, ligados);
            
        }
        
        //Para Todos os Gateway
        for (Gateway gate : gateways.values()) {
            List<Element> ligados = new LinkedList<Element>();
            for(Arc arco: arcos.values() ){
                if(arco.getSource() == gate){
                    ligados.add(arco.getTarget());
                }
            }
            gate.setTipo("Gateway");
            todosOsElementos.put(gate, ligados);
            
        }
        
        //Para Todos os DataStore
        for (DataStore dataSto : dataStores.values()) {
            List<Element> ligados = new LinkedList<Element>();
            for(Arc arco: arcos.values() ){
                if(arco.getSource() == dataSto){
                    ligados.add(arco.getTarget());
                }
            }
            dataSto.setTipo("DataStore");
            todosOsElementos.put(dataSto, ligados);
            
        }
        
        //Para Todos os DataObjects
        for (DataObject dataObj : dataObjects.values()) {
            List<Element> ligados = new LinkedList<Element>();
            for(Arc arco: arcos.values() ){
                if(arco.getSource() == dataObj){
                    ligados.add(arco.getTarget());
                }
            }
            dataObj.setTipo("DataObject");
            todosOsElementos.put(dataObj, ligados);            
        }
        
        model.setTodosOsElementos(todosOsElementos);
    }
    
    public static List<List> findSequentialActivities (ProcessModel model){
        
        HashMap<Element, List<Element>> todosOsElementos = model.getTodosOsElementos();
        List<List> atividadesTotais = new LinkedList<List>();
        
        for(Element elem: todosOsElementos.keySet()){
            if(elem.getTipo().equalsIgnoreCase("atividade")){
                List<Element> listaAtiv = new LinkedList<Element>();
                List<Element> ligados = todosOsElementos.get(elem);
                for(Element elem2: ligados){
                    if(elem2.getTipo().equalsIgnoreCase("atividade")){
                        //vai chamar função recursiva
                        listaAtiv.add(elem);
                        listaAtiv.add(elem2);                        
                        obterAtividadesSeq(model,listaAtiv, elem2);
                    }                  
                    if(elem2.getTipo().equalsIgnoreCase("evento")){
                        //vai chamar função recursiva
                        listaAtiv.add(elem);
                        obterAtividadesSeq(model,listaAtiv, elem2);
                    }
                }
                if(listaAtiv.size()>1){
                    atividadesTotais.add(listaAtiv);
                }
            }            
        }
        
        return consolidarAtivSeq(atividadesTotais);    
    }
        
    private static void obterAtividadesSeq (ProcessModel model, List<Element> listaAtiv, Element elem2){
        
        HashMap<Element, List<Element>> todosOsElementos = model.getTodosOsElementos();
        List<Element> ligados = todosOsElementos.get(elem2);
        for(Element elem3: ligados){
            if (elem3.getTipo().equalsIgnoreCase("atividade")) {
                //vai chamar função recursiva
                if (!listaAtiv.contains(elem3)) {
                    listaAtiv.add(elem3);
                }
                obterAtividadesSeq(model, listaAtiv, elem3);
            }
             if (elem3.getTipo().equalsIgnoreCase("evento")) {
                //vai chamar função recursiva
                obterAtividadesSeq(model, listaAtiv, elem3);
            }
        }
    }
    
    private static List<List> consolidarAtivSeq(List<List> atividadesTotais){ 
        List<List> listAux = new LinkedList<List>();
        
        for (List listAtiv : atividadesTotais) {
            for(List listAtiv2: atividadesTotais){
                if( (!(listAtiv.equals(listAtiv2))) && (listAtiv.containsAll(listAtiv2))){
                    listAux.add(listAtiv2);
                }               
            }
        }
        atividadesTotais.removeAll(listAux);
        return atividadesTotais;
    }
    
    public static List<ServiceInformation> deleteSameServices(List<ServiceInformation> listAllServices){
        
        List<ServiceInformation> repeatServices = new LinkedList<ServiceInformation>();
        for(int i =0;i<listAllServices.size();i++){
            String name = listAllServices.get(i).getName();
            List<String> allProf = listAllServices.get(i).getProfile();
            List<String> allAct = listAllServices.get(i).getActivities();
            
            for(int j=i+1;j<listAllServices.size();j++){
                String name2 = listAllServices.get(j).getName();
                
                if(name.equalsIgnoreCase(name2)){
                    List<String> allProf2 = listAllServices.get(j).getProfile();      
                    for (String prof2 : allProf2) {
                        if(!allProf.contains(prof2)){
                            allProf.add(prof2);
                        }                        
                    }
                    
                    List<String> allAct2 = listAllServices.get(j).getActivities();
                    for (String act2 : allAct2) {
                        if(!allAct.contains(act2)){
                            allAct.add(act2);
                        }                        
                    }
                    
                        ServiceInformation serv = listAllServices.get(j);
                        repeatServices.add(serv);
                }
            }            
        }
        listAllServices.removeAll(repeatServices);
        return listAllServices;        
    }
    
    public static List<ServiceInformation> countSubflows(List<ServiceInformation> allWorkflowServices){
        
        for (int i=0; i<allWorkflowServices.size();i++) {
            List<String> activities1 = allWorkflowServices.get(i).getActivities();
            int countSubflows = 0;
            
            for(int j=i+1;j<allWorkflowServices.size();j++){
                List<String> activities2 = allWorkflowServices.get(j).getActivities();                
                if(activities1.containsAll(activities2)){
                    countSubflows ++;
                }                
            }
            allWorkflowServices.get(i).setSubflows(countSubflows);
        }        
        return allWorkflowServices;
    }

    public static List<ServiceInformation> consolidateClusterServices(List<ServiceInformation> listServicesCluster) {
        
        List<ServiceInformation> listDeleteCluster = new LinkedList<ServiceInformation>();
        List<ServiceInformation> listNewCluster = new LinkedList<ServiceInformation>();
        List<ServiceInformation> allServicesCluster = listServicesCluster;
        
        for (int i = 0; i < allServicesCluster.size(); i++) {
            String name1 = allServicesCluster.get(i).getOriginalName();
            String type1 = allServicesCluster.get(i).getType();
            for (int j = i+1; j < allServicesCluster.size(); j++) {
                String name2 = allServicesCluster.get(j).getOriginalName();
                String type2 = allServicesCluster.get(j).getType();
                if( (name1.equalsIgnoreCase(name2)) &&
                    (!type1.equalsIgnoreCase(type2)) ){
                    //apagar os dois serviços da lista
                    listDeleteCluster.add(allServicesCluster.get(i));
                    listDeleteCluster.add(allServicesCluster.get(j));
                    
                    //criando novo serviço consolidado
                    ServiceInformation newCluster = new ServiceInformation();
                    
                    List<String> act = new LinkedList<String>();
                    //verificando se a atividade dos dois serviço são diferentes
                    List<String> activity1 = allServicesCluster.get(i).getActivities();
                    List<String> activity2 = allServicesCluster.get(j).getActivities();
                    if(!activity1.get(0).equalsIgnoreCase(activity2.get(0))){                        
                        act.add(activity1.get(0));
                        act.add(activity2.get(0));
                    }
                    else{
                        act.add(activity1.get(0));
                    }
                    newCluster.setActivities(act);
                    
                    
                    if(!allServicesCluster.get(i).getEntry().isEmpty()){
                        newCluster.setEntry(allServicesCluster.get(i).getEntry());
                    }
                    if(!allServicesCluster.get(j).getEntry().isEmpty()){
                        newCluster.setEntry(allServicesCluster.get(j).getEntry());
                    }
                    
                    if(!allServicesCluster.get(i).getExit().isEmpty()){
                        newCluster.setExit(allServicesCluster.get(i).getExit());
                    }
                    if(!allServicesCluster.get(j).getExit().isEmpty()){
                        newCluster.setExit(allServicesCluster.get(j).getExit());
                    }
                    
                   
                    
                    newCluster.setOriginalName(allServicesCluster.get(i).getOriginalName());
                    
                    newCluster.setName("Armazenar e Obter " + newCluster.getOriginalName());
                   
                    newCluster.setDescription("A partir dos dados " + newCluster.getEntry() +" deve-se armazenar e obter "+  newCluster.getOriginalName() + ".");                    
                    
                    List<String> perfil2 = allServicesCluster.get(j).getProfile();
                    for (String per : perfil2) {
                        if(!allServicesCluster.get(i).getProfile().contains(per)){
                            allServicesCluster.get(i).getProfile().add(per);
                        }
                    }                    
                    newCluster.setProfile(allServicesCluster.get(i).getProfile());
                    newCluster.setSubflows(0);
                    newCluster.setType("Dados");
                    newCluster.setOrigin("Cluster");
                    
                    listNewCluster.add(newCluster);
                   
                }
                  
            }
            
        }
        allServicesCluster.removeAll(listDeleteCluster);
        allServicesCluster.addAll(listNewCluster);
        return allServicesCluster;
    }
    
}
